#!/usr/bin/env python
# -*- coding: utf8 -*-
# title       :
# description :
# author      :'ShenMeng'


import unreal_engine as ue

from unreal_engine.classes import StaticMesh, StaticMeshActor, Package
from unreal_engine.classes import ParticleSystem, Emitter
from unreal_engine.classes import LevelSequence, LevelSequenceActor, LevelSequenceFactoryNew
from unreal_engine.structs import SoftObjectPath
from unreal_engine.classes import MovieSceneAudioTrack
from unreal_engine.classes import Material
from unreal_engine.classes import Skeleton
from unreal_engine.classes import Level, World, WorldFactory

from unreal_engine.classes import FbxImportUI, PyFbxFactory

import collections
import re


#######################################################################
# prviate function
def _objValidate(obj, objType):
    result = []
    if obj.is_a(objType):
        result.append(obj)
    return result

def getWorld():
    return ue.get_editor_world()
    
#######################################################################    
# actor public function
def pyType(type):
    """
    return: {asset:assetType, actor:actorType}
    """
    typeData = None
    typeDict = {"StaticMesh":dict(asset=StaticMesh, actor=StaticMeshActor), 
                "LevelSequence":dict(asset=LevelSequence, actor=LevelSequenceActor, factory=LevelSequenceFactoryNew),
                "ParticleSystem":dict(asset=ParticleSystem, actor=Emitter),
                "Material":dict(asset=Material),
                "Skeleton":dict(asset=Skeleton),
                "Level":dict(asset=World, actor=World, factory=WorldFactory)
                }
    if type:
        if type in typeDict:
            typeData = typeDict.get(type)
        else:
            raise ValueError("type error!")
    return typeData
    
def pyActor(name):
    world = getWorld()
    actor = world.find_actor_by_label(name)
    return actor
    
def getAllActors():
    world = getWorld()
    return world.all_actors() 
    
def ls(object, regex=None, type=None, sl=False, subdir=False, path=None):
    """
    regex: re syntax
    type: staticMesh, levelSequence,...
    """
    resultObjects = []
    if object == 'actor':
        if sl:
            allObjects = ue.editor_get_selected_actors()
        else:
            allObjects = getAllActors()
        # if (not regex) and (not type):
            # return allObjects
    elif object == 'asset':
        if sl:
            allObjects = ue.get_selected_assets()
        else:
            if path:
                allObjects = ue.get_assets(path, subdir)
            elif type:
                allObjects = ue.get_assets_by_class(type)
    typeData = pyType(type)
    for obj in allObjects:
        if regex:
            # name = actor.get_name()
            name = obj.get_display_name()
            result = re.search(regex, name)
            if result:
                if typeData:
                    resultObjects.extend(_objValidate(obj, typeData.get(object)))
                else:
                    resultObjects.append(obj)
        elif typeData:
            resultObjects.extend(_objValidate(obj, typeData.get(object)))
        else:
            resultObjects = allObjects
            break
    return resultObjects

def actorImporter(asset, name=None):
    strList = asset.__str__().split(' ')
    index = strList.index('UClass') + 1
    typeStr = strList[index][1:-1]
    typeData = pyType(typeStr)
    world = getWorld()
    actor = world.actor_spawn(typeData.get('actor'))
    if name:
        actor.set_name(name)
        actor.set_actor_label(name)
    if typeStr == 'LevelSequence':
        actor.actor_set_level_sequence(asset)
        # actor.LevelSequence = SoftObjectPath(AssetPathName=asset.get_path_name())
    elif typeStr == 'StaticMesh':
        actor.StaticMeshComponent.StaticMesh = ue.load_object(typeData.get('asset'), asset.get_path_name())
    elif typeStr == 'ParticleSystem':
        actor.ParticleSystemComponent.Template = ue.load_object(typeData.get('asset'), asset.get_path_name())
    
#######################################################################    
# asset public function  
def fbxImporter(fbxPath, contentPath, mesh=True, animation=False, material=False, texture=False, skeleton=None, asSkeletal=True, step=None, type=None):
    """
    asset = fbxImporter('D:/test/aaa.fbx', '/Game/aa', step='surfacing')
    """
    #fbxUi = ue.new_object(FbxImportUI)
    # fbxUi.properties()
    factory = PyFbxFactory()
    if step:
        # template
        if step == 'surfacing':
            meshType = 0
            mesh = True
            asSkeletal = False
            animation = False
            material = False
            texture = False
        elif step == 'rigging':
            meshType = 1
            asSkeletal = True
            mesh = True
            animation = False
            material = False
            texture = False
        elif step == 'animation':
            meshType = 2
            asSkeletal = False
            mesh = False
            animation = True
            material = False
            texture = False
            if skeleton:
                factory.ImportUI.Skeleton = skeleton
            else:
                raise ValueError("Skeleton Value error")
        else:
            raise ValueError("type value error")
    else:
        if not mesh:
            if skeleton:
                factory.ImportUI.Skeleton = skeleton
            else:
                raise ValueError("Skeleton Value error")
        if type == 'StaticMesh':meshType=0
        elif type == 'SkeletalMesh':meshType=1
        elif type == 'Animation':meshType=2
        else:meshType=0
    
    #fbxUi.set_property('bImportTextures', texture)
    #ue.set_fbx_import_option(fbxUi)
    #ue.import_asset(fbxPath, contentPath, PyFbxFactory)
    factory.ImportUI.MeshTypeToImport = meshType
    factory.ImportUI.bImportAsSkeletal = (True if asSkeletal else False)
    factory.ImportUI.bImportMesh = (True if mesh else False)
    factory.ImportUI.bImportAnimations = (True if animation else False)
    factory.ImportUI.bImportMaterials = (True if material else False)
    factory.ImportUI.bImportTextures = (True if texture else False) 
    return factory.factory_import_object(fbxPath, contentPath)
    
# TODO
def assetCreater(type, path, name):
    asset = None
    assetSavePath = "{}/{}".format(path, name)
    typeData = pyType(type)
    try:
        asset = ue.get_asset(assetSavePath)
    except:
        factoryClass = typeData.get('factory', None)
        if factoryClass:
            factory = factoryClass()
            asset = factory.factory_create_new(assetSavePath)
        else:
            assetType = typeData.get('asset')
            asset = assetType(name)
            asset.save_package(assetSavePath)
    return asset





